package yerr

import (
	"errors"
	"fmt"
)

func New() *YError {
	return &YError{}
}

func NewCode(code YCode) *YError {
	return &YError{
		code: code,
	}
}

func NewFull(code YCode, msg string, err error) *YError {
	return &YError{
		code: code,
		msg:  msg,
		err:  err,
	}
}

type YError struct {
	code YCode
	msg  string
	err  error
}

func (e *YError) Code() YCode {
	return e.code
}

func (e *YError) Msg() string {
	return e.msg
}

func (e *YError) Err() error {
	return e.err
}

func (e *YError) WithCode(code YCode) *YError {
	e.code = code
	return e
}

func (e *YError) WithMsg(msg string, ars ...any) *YError {
	m := fmt.Sprintf(msg, ars...)
	if m != "" {
		e.msg = m
	}
	return e
}

func (e *YError) WithErr(err error) *YError {
	e.err = err
	return e
}

func (e *YError) Error() string {
	if e.err == nil {
		return e.msg
	}

	newE := errors.Join(e.err, fmt.Errorf("%s", e.msg))
	return newE.Error()
}
